package com.service.admin.support;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.kevinsawicki.http.HttpRequest;
import com.jsoniter.JsonIterator;
import com.jsoniter.any.Any;
import com.jsoniter.output.JsonStream;
import com.service.admin.admin.dto.LoginUserSession;
import com.service.admin.utils.MemCacheNoTran;
import com.service.core.exception.CommonException;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * <dl>
 * <dt>platform</dt>
 * <dd>Description:</dd>
 * <dd>Copyright: Copyright (C) 2018</dd>
 * <dd>Company: </dd>
 * <dd>CreateDate: 2019-04-05</dd>
 * </dl>
 */
@Component
@Slf4j
public class SessionUtil {

    @Autowired
    private MemCache memCache;

    @Autowired
    private MemCacheNoTran memCacheNoTran;

    @Autowired
    private ProjectProperty projectProperty;

    @Autowired
    private Environment env;

    private final String loginSessionKey = "admin_user_";

    public String savSession(LoginUserSession loginUserSession) {
        String token = generateToken(loginUserSession);
        String jsonObject = JSONObject.toJSONString(loginUserSession);
        memCache.setNoExpire(token, jsonObject);
        return token;
    }

    public void refreshSession(LoginUserSession loginUserSession) {
        String token = generateToken(loginUserSession);
        String jsonObject = JSONObject.toJSONString(loginUserSession);
        memCache.setNoExpire(Token.TOKEN.get(), jsonObject);
    }

    public void savSessionId(Integer uid, String sessionId) {
        memCache.setNoExpire("admin:session:" + uid, sessionId);
    }

    public String getSessionId(Integer uid) {
        return memCache.get("admin:session:" + uid);
    }

    public LoginUserSession getUser() {
        String token = Token.TOKEN.get();
        if (token == null) {
            return null;
        }
        String jsonObject = memCache.get(token);
        return JSON.parseObject(jsonObject, LoginUserSession.class);
    }

    public LoginUserSession getUserWithoutRedisTran() {
        String token = Token.TOKEN.get();
        if (token == null) {
            return null;
        }
        String jsonObject = memCacheNoTran.get(token);
        return JSON.parseObject(jsonObject, LoginUserSession.class);
    }

    private String generateToken(LoginUserSession loginUserSession) {
        String URL = projectProperty.getTokenServiceBaseUrl() + "/token/generate";
        Map<String, Object> map = new HashMap<>();
        map.put("id", loginUserSession.getId());
        map.put("userName", loginUserSession.getLoginName());
        map.put("nickName", loginUserSession.getNickName());
        map.put("mobile", loginUserSession.getMobile());
        map.put("email", loginUserSession.getEmail());
        map.put("sessionId", loginUserSession.getSessionId());
        map.put("source", "END_USER");

        String serialize = JsonStream.serialize(map);
        HttpRequest httpRequest = HttpRequest.post(URL).header("api-version", 1.0)
                .header("Authorization", projectProperty.getTokenServiceAuthorization())
                .acceptJson().contentType("application/json", "UTF-8")
                .send(serialize.getBytes());

        int code = httpRequest.code();
        String body = httpRequest.body();
        log.debug("用户<mobile:{}> 签发验证结果:{}", loginUserSession.getMobile(), body);
        Any bodyAny = JsonIterator.deserialize(body);
        int status = bodyAny.get("status").toInt();
        if (HttpStatus.OK.value() != code || HttpStatus.OK.value() != status) {
            throw new CommonException("签发验证失败", "token_fail");
        } else {
            return bodyAny.get("data").get("token").toString();
        }
    }

    public void removeSession() {
        String token = Token.TOKEN.get();
        memCache.delete(token);
    }
}
